import DocumentUtil from './document';
/**
 * @class 帮助类
 * @description 帮助类
 * @constructor
 */

class Utils extends DocumentUtil {
  constructor() {
    super();
    this.cssVendors = ['ms', 'moz', 'webkit', 'o'];
  }

  /**
   * @function addStylePrefix 添加样式前缀
   * @param {string} obj 目标对象
   * @param {string} key 建
   * @param {string} value 值
   * @return 无返回
   */
  addStylePrefix(obj, key, value) {
    for (const item in this.cssVendors) {
      obj[`-${this.cssVendors[item]}-${key}`] = `${value}`
    }
  }

  /**
   * @function manualReSize 手动触发resize
   * @return 无返回
   */
  manualReSize() {
    if (document.createEvent) {
      var event = document.createEvent("HTMLEvents");
      event.initEvent("resize", true, true);
      window.dispatchEvent(event);
    } else if (document.createEventObject) {
      window.fireEvent("onresize");
    }
  }

  /**
   * @function animationThrottle 动画节流
   * @param {function} fn 动画函数
   * @return 无返回
   */
  animationThrottle(fn) {
    let ticking = false;
    const update = function () {
      ticking = false;
      fn && fn.apply(this, arguments);
    }

    if (!ticking) {
      requestAnimationFrame(update);
    }
    ticking = true;
  }

  /**
   * @function getEventTarget 获取事件源
   * @param {object} ev 事件对象
   * @return {obejct} 事件源
   */
  getEventTarget(ev) {
    const event = ev || window.event;
    return event.srcElement || event.target;
  }

  /**
   * @function mouseArea 区域判断
   * @param {object} ctl 区域对象
   * @param {object} evt 事件对象
   * @return {array} 区域数组
   */
  mouseArea(ctl, evt) {
    evt = evt || window.event;
    const x = evt.pageX - ctl.offset().left;
    const y = evt.pageY - ctl.offset().top;
    const wBlock = ctl.width() / 2;
    const hBlock = ctl.height() / 2;
    const wSmallBlock = ctl.width() / 3;
    const hSmallBlock = ctl.height() / 4;

    let position = [];

    // 先获取基本位置
    if (x <= wBlock) {
      position[0] = 'left';
    } else if (x > wBlock) {
      position[0] = 'right';
    }
    if (y <= hBlock) {
      position[1] = 'top';
    } else if (y >= hBlock) {
      position[1] = 'bottom';
    }

    // 再判断是否在中心区块
    if (x > wSmallBlock && x < wSmallBlock * 2 && y > hSmallBlock && y < hSmallBlock * 3) {
      position = ['center'];
    }

    return position;
  }

  /**
   * @function toolGetPercentSplit 获取指定百分比所在等分区间
   * @param {number} pos 百分比 (0-100)
   * @param {number} num 分割数量
   * @return {number} 区间数值
   */
  toolGetPercentSplit(pos, num) {
    const max = num - 1;
    const numSplit = 100 / max; // 宽度边界
    const numHalf = numSplit / 2;
    let numTemp = 0;
    for (let i = 0; i <= max; i++) {
      numTemp = 100 * i / max;
      if (pos <= numTemp + numHalf && pos >= numTemp - numHalf) {
        return i + 1;
      }
    }
    return 1;
  };

  /**
   * @function toolGetNumSplit 获取百分比区间
   * @param {number} v 数值 (1-num)
   * @param {number} num 分割数量
   * @return {array} 区间数组
   */
  toolGetNumSplit(v, num) {
    const max = num - 1;
    const numSplit = 100 / max; // 宽度边界
    const numHalf = numSplit / 2;
    const numLeft = (v - 1) * 100 / max;
    return [Math.max(0, numLeft - numHalf + 0.0000000000001), numLeft, Math.min(100, numLeft + numHalf)];
  };

  /**
   * @function setHabit 设置用户习惯cookie
   * @param {number} name habit键
   * @param {number} key habit子键
   * @param {number} value habit子键值
   * @return 无
   */
  setHabit(name, key, value) {
    const habit = JSON.parse(this.cookie(name)) || {};
    habit[key] = value;
    this.cookie(name, JSON.stringify(habit));
  }

  /**
   * @function getInstance 获取对象实例
   * @param {class|object} classOrObject 需要实例化的
   * @param {object} options 实例化参数
   * @return {object}
   */
  getInstance(classOrObject, options) {
    return this.couldBeClass(classOrObject) ? new classOrObject(options) : classOrObject;
  }

  /**
   * @function couldBeClass 是否是类
   * @param {class|object} obj 验证对象
   * @param {boolean} strict 是否使用严格模式
   * @return {boolean} true|false
   */
  couldBeClass(obj, strict) {
    debugger
    if (typeof obj != "function") return false;

    var str = obj.toString();

    // async function or arrow function
    if (obj.prototype === undefined) return false;
    // generator function or malformed definition
    if (obj.prototype.constructor !== obj) return false;
    // ES6 class
    if (str.slice(0, 5) == "class") return true;
    // has own prototype properties
    if (Object.getOwnPropertyNames(obj.prototype).length >= 2) return true;
    // anonymous function
    if (/^function\s+\(|^function\s+anonymous\(/.test(str)) return false;
    // ES5 class without `this` in the body and the name's first character
    // upper-cased.
    if (strict && /^function\s+[A-Z]/.test(str)) return true;
    // has `this` in the body
    if (/\b\(this\b|\bthis[\.\[]\b/.test(str)) {
      // not strict or ES5 class generated by babel
      if (!strict || /classCallCheck\(this/.test(str)) return true;

      return /^function\sdefault_\d+\s*\(/.test(str);
    }
    return false;
  }

  // 是否移动端
  isMobileHanddle() {
    var UA = navigator.userAgent;
    // 判断是否手机用户，排除IPAD
    return (screen.width / screen.height < 1 || /AppleWebKit.*Mobile/i.test(UA) ||
      /MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/
        .test(UA)) &&
      !/ipad/gi.test(UA);
  }

  /**
   * @function 简单cookie获取与设置
   * @param  {string} name  cookie设置或获取
   * @param  {string} value 设置cookie的值
   * @param  {string} options  设置cookie的参数
   */
  cookie(name, value, options) {
    options = options || {};
    if (typeof value !== 'undefined') {
      if (value === null) {
        options.expires = -1; // 删除
      }
      const date = new Date();

      if (options.expires) {
        date.setTime(date.getTime() + options.expires * 36e5); // 以小时为单位
      }
      document.cookie = name + '=' + encodeURIComponent(value) + ';' +
        (options.expires ? 'expires=' + date.toGMTString() + ';' : '') +
        'path=/;' + (options.domain ? 'domain=' + options.domain + ';' : '');
    } else {
      const reg = new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$');

      return decodeURIComponent(document.cookie.replace(reg, '$1')) || null;
    }
  }

  /**
   * @function cookieParse 对cookie获取后进行对象解析
   * @param  {string} name  cookie设置或获取
   * @param  {Object} value 设置cookie的值
   * @param  {string} options  设置cookie的参数
   */
  cookieParse(name, value, options) {
    if (value === undefined) {
      let data = this.cookie(name);
      let tmpData = null;
      try {
        tmpData = JSON.parse(decodeURIComponent(data));
      } catch (err) {
        tmpData = decodeURIComponent(data);
      }
      return tmpData;
    } else {
      this.cookie(name, (typeof value === 'string' || value === null) ? value : JSON.stringify(value), options);
    }
  }

  /**
   * 用于支持对象合并。将对象合并到prototype上，使得能够支持扩展
   * Examples:
   * ```
   * // 媒体管理（上传、下载）
   * API.mixin(require('./lib/api_media'));
   * ```
   * @param {Object} obj 要合并的对象
   */
  mixin(mixinObj, obj, ismixin=true) {
    for (let key in obj) {
      if (mixinObj.hasOwnProperty(key)) {
        throw new Error('Don\'t allow override existed prototype method. method: ' + key);
      }
      mixinObj[key] = (...args) => {
        if (ismixin) {
          obj[key](...args);
        }
      }
    }
  };

  /**
   * @function singleton 创建单例方法
   */
  singleton(ClassObject) {
    let instance;
    return function (...args) {
      if (!instance) {
        instance = new ClassObject(...args);
      }
      return instance;
    };
  }

  /**
   * @function defaultCamelize 默认驼峰话文件
   * @param {String} fileString
   * @param {String} caseStyle 驼峰风格lower(小写),upper（大写）,camel（驼峰）
   * use default camelize, will capitalize the first letter
   * foo_bar.js > FooBar
   * fooBar.js  > FooBar
   * FooBar.js  > FooBar
   * FooBar.js  > FooBar
   * FooBar.js  > fooBar (if lowercaseFirst is true)
   */
  defaultCamelize(fileName, caseStyle) {
    if (!/^[a-z][a-z0-9_-]*$/i.test(fileName)) {
      throw new Error(`${fileName} is not match 'a-z0-9_-'`);
    }
    fileName = fileName.replace(/[_-][a-z]/gi, s =>
      s.substring(1).toUpperCase()
    );
    let first = fileName[0];
    switch (caseStyle) {
      case 'lower':
        first = first.toLowerCase();
        break;
      case 'upper':
        first = first.toUpperCase();
        break;
      case 'camel':
      default:
    }
    return first + fileName.substring(1);
  }
  /**
   * @function getTargetAttr 获取目标属性
   * @return {object}
   */
  getChapterDataset(dom) {
    let { chapterId, chapterIndex } = dom.dataset;
    chapterId = parseInt(chapterId, 10);
    chapterIndex = parseInt(chapterIndex, 10);
    return { chapterId, chapterIndex };
  }

  /**
   * @function isSupportWebp 判断浏览器是否支持web格式
   * @return {[Boolean]}
   */
  isSupportWebp() {
    try {
      return document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') === 0;
    } catch (err) {
      return false;
    }
  }

  /**
   * @function switchWebp web图片逻辑处理
   * @param {String} src 图片地址
   * @param {String} rules 图片规则
   * @return {String} 返回组装webp后的图片地址
   */
  switchWebp(src, rules = '-normal') {
    // gif图片规则只能加-normal压缩，或者原图，因为不支持webp格式
    const isGif = /\.gif$/.test(src);
    const arrSrc = src.split('?');
    src = arrSrc[0];
    const search = arrSrc[1] ? `?${arrSrc[1]}` : '';
    // 匹配图片规格根据规格处理图片
    const sizeRegExp = /\.(png|jpg|jpeg|gif)-((\d+)x(\d+))/gi;
    if (!sizeRegExp.test(src) || isGif || !this.isSupportWebp()) {
      src = src + rules;
    }
    if (this.isSupportWebp() && !/(\.webp)$/.test(src)) {
      src = src + '.webp';
    }
    return src + search;
  }
}

export default new Utils();
